﻿//
//  HFBaseHTTPRequestManager.m
//  Pods
//
//  Created by admin on 2020/4/10.
//

#import "HFBaseHTTPRequestManager.h"
#import "HFLogger.h"

typedef NS_ENUM(NSInteger, HFBaseHTTPRequestSerializerType) {
    HFBaseHTTPRequestSerializerTypeNone,
    HFBaseHTTPRequestSerializerTypeHuaTi,
    HFBaseHTTPRequestSerializerTypeLaiJuCai,
    HFBaseHTTPRequestSerializerTypeLaiJuCaiSign,
};

@interface HFBaseHTTPRequestManager ()

@property (nonatomic, strong) AFURLSessionManager *URLSessionManager;
/// 蓝知专用
@property (nonatomic, strong) AFHTTPRequestSerializer<AFURLRequestSerialization> *htRequestSerializer;
/// 来聚财专用
@property (nonatomic, strong) AFHTTPRequestSerializer<AFURLRequestSerialization> *ljcRequestSerializer;
/// 来聚财请求头带sign专用
@property (nonatomic, strong) AFHTTPRequestSerializer<AFURLRequestSerialization> *ljcSignRequestSerializer;

@end

@implementation HFBaseHTTPRequestManager

+ (instancetype)manager {
    static HFBaseHTTPRequestManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[self alloc] init];
    });
    return manager;
}

+ (NSURLSessionDataTask *)HTPOST:(NSString *)URLString
                      parameters:(id)parameters
                         success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                         failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager dataTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeHuaTi HTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    [task resume];
    return task;
}

+ (NSURLSessionDataTask *)LJCPOST:(NSString *)URLString
                       parameters:(id)parameters
                          success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager dataTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeLaiJuCai HTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    [task resume];
    return task;
}

+ (NSURLSessionDataTask *)LJCSignPOST:(NSString *)URLString
                           parameters:(id)parameters
                              success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                              failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager dataTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeLaiJuCaiSign HTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    [task resume];
    return task;
}

+ (NSURLSessionDataTask *)HTGET:(NSString *)URLString
                     parameters:(id)parameters
                        success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                        failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager dataTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeHuaTi HTTPMethod:@"GET" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    [task resume];
    return task;
}

+ (NSURLSessionDataTask *)LJCGET:(NSString *)URLString
                      parameters:(id)parameters
                         success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                         failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager dataTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeLaiJuCai HTTPMethod:@"GET" URLString:URLString parameters:parameters uploadProgress:nil downloadProgress:nil success:success failure:failure];
    [task resume];
    return task;
}

+ (NSURLSessionDataTask *)HTPOST:(NSString *)URLString
                      parameters:(id)parameters
       constructingBodyWithBlock:(void(^)(id <AFMultipartFormData> formData))block
                        progress:(void(^)(NSProgress *uploadProgress))uploadProgress
                         success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                         failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager uploadTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeHuaTi URLString:URLString parameters:parameters constructingBodyWithBlock:block progress:uploadProgress success:success failure:failure];
    [task resume];
    return task;
}

+ (NSURLSessionDataTask *)LJCPOST:(NSString *)URLString
                       parameters:(id)parameters
        constructingBodyWithBlock:(void(^)(id <AFMultipartFormData> formData))block
                         progress:(void(^)(NSProgress *uploadProgress))uploadProgress
                          success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                          failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    NSURLSessionDataTask *task = [self.manager uploadTaskWithRequestSerializerType:HFBaseHTTPRequestSerializerTypeLaiJuCai URLString:URLString parameters:parameters constructingBodyWithBlock:block progress:uploadProgress success:success failure:failure];
    [task resume];
    return task;
}

+ (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
    [self.manager.htRequestSerializer setValue:value forHTTPHeaderField:field];
    [self.manager.ljcRequestSerializer setValue:value forHTTPHeaderField:field];
    [self.manager.ljcSignRequestSerializer setValue:value forHTTPHeaderField:field];
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.URLSessionManager = [[AFURLSessionManager alloc] init];
        AFHTTPResponseSerializer <AFURLResponseSerialization> *responseSerializer = self.URLSessionManager.responseSerializer;
        responseSerializer.acceptableContentTypes = [NSSet setWithArray:@[
            @"application/json",
            @"text/json",
            @"text/html",
            @"text/plain"
        ]];

        self.htRequestSerializer = [AFHTTPRequestSerializer serializer];
        self.htRequestSerializer.timeoutInterval = 10;
        [self.htRequestSerializer setValue:@"keep-alive" forHTTPHeaderField:@"Connection"];

        self.ljcRequestSerializer = [AFHTTPRequestSerializer serializer];
        self.ljcRequestSerializer.timeoutInterval = 15;
        [self.ljcRequestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
        
        self.ljcSignRequestSerializer = [AFHTTPRequestSerializer serializer];
        self.ljcSignRequestSerializer.timeoutInterval = 15;
        [self.ljcSignRequestSerializer setValue:@"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    }
    return self;
}

#pragma mark - CompletionHandler

- (NSURLSessionDataTask *)dataTaskWithRequestSerializerType:(HFBaseHTTPRequestSerializerType)requestSerializerType
                                                 HTTPMethod:(NSString *)method
                                                  URLString:(NSString *)URLString
                                                 parameters:(id)parameters
                                             uploadProgress:(void(^)(NSProgress *uploadProgress))uploadProgress
                                           downloadProgress:(void(^)(NSProgress *downloadProgress))downloadProgress
                                                    success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                                                    failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    __block NSURLSessionDataTask *task = nil;
    task = [self dataTaskWithRequestSerializerType:requestSerializerType HTTPMethod:method URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:downloadProgress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        NSMutableArray *parameterStrings = [NSMutableArray array];
        [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parameterStrings addObject:[NSString stringWithFormat:@"%@=%@", key, obj]];
        }];
        HFLogger(@"%@?%@", URLString, [parameterStrings componentsJoinedByString:@"&"]);
        HFLogger(@"\n%@\n%@\n%@\n%@\n%@\n", URLString, task.currentRequest.allHTTPHeaderFields, parameters, responseObject, error);

        if (error) {
            if (failure) {
                failure(task, error);
            }
        } else {
            if (success) {
                success(task, responseObject);
            }
        }
    }];
    return task;
}

- (NSURLSessionUploadTask *)uploadTaskWithRequestSerializerType:(HFBaseHTTPRequestSerializerType)requestSerializerType
                                                      URLString:(NSString *)URLString
                                                     parameters:(id)parameters
                                      constructingBodyWithBlock:(void(^)(id <AFMultipartFormData> formData))block
                                                       progress:(void(^)(NSProgress *uploadProgress))uploadProgress
                                                        success:(void(^)(NSURLSessionDataTask *task, id responseObject))success
                                                        failure:(void(^)(NSURLSessionDataTask *task, NSError *error))failure {
    __block NSURLSessionUploadTask *task = nil;
    task = [self uploadTaskWithRequestSerializerType:requestSerializerType URLString:URLString parameters:parameters constructingBodyWithBlock:block progress:uploadProgress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        NSMutableArray *parameterStrings = [NSMutableArray array];
        [parameters enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
            [parameterStrings addObject:[NSString stringWithFormat:@"%@=%@", key, obj]];
        }];
        HFLogger(@"%@?%@", URLString, [parameterStrings componentsJoinedByString:@"&"]);
        HFLogger(@"\n%@\n%@\n%@\n%@\n%@\n", URLString, task.currentRequest.allHTTPHeaderFields, parameters, responseObject, error);

        if (error) {
            if (failure) {
                failure(task, error);
            }
        } else {
            if (success) {
                success(task, responseObject);
            }
        }
    }];
    return task;
}

#pragma mark - URLRequest

- (NSURLSessionDataTask *)dataTaskWithRequestSerializerType:(HFBaseHTTPRequestSerializerType)requestSerializerType
                                                 HTTPMethod:(NSString *)method
                                                  URLString:(NSString *)URLString
                                                 parameters:(id)parameters
                                             uploadProgress:(void(^)(NSProgress *uploadProgress))uploadProgress
                                           downloadProgress:(void(^)(NSProgress *downloadProgress))downloadProgress
                                          completionHandler:(void(^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {
    NSError *serializationError = nil;
    NSMutableURLRequest *request = nil;
    
    if (requestSerializerType == HFBaseHTTPRequestSerializerTypeHuaTi) {
        request = [self.htRequestSerializer requestWithMethod:method URLString:URLString parameters:parameters error:&serializationError];
    } else if (requestSerializerType == HFBaseHTTPRequestSerializerTypeLaiJuCai) {
        request = [self.ljcRequestSerializer requestWithMethod:method URLString:URLString parameters:parameters error:&serializationError];
    } else if (requestSerializerType == HFBaseHTTPRequestSerializerTypeLaiJuCaiSign) {
        request = [self.ljcSignRequestSerializer requestWithMethod:method URLString:URLString parameters:parameters error:&serializationError];
    } else {
        if (completionHandler) {
            dispatch_async(self.URLSessionManager.completionQueue ?: dispatch_get_main_queue(), ^{
                completionHandler(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{
                    NSLocalizedDescriptionKey: @"Invalid Request Serializer Type In HTTP Request Manager",
                }]);
            });
        }
        return nil;
    }
    
    if (serializationError) {
        if (completionHandler) {
            dispatch_async(self.URLSessionManager.completionQueue ?: dispatch_get_main_queue(), ^{
                completionHandler(nil, nil, serializationError);
            });
        }
        return nil;
    }
    
    return [self dataTaskWithRequest:request uploadProgress:uploadProgress downloadProgress:downloadProgress completionHandler:completionHandler];
}

- (NSURLSessionUploadTask *)uploadTaskWithRequestSerializerType:(HFBaseHTTPRequestSerializerType)requestSerializerType
                                                      URLString:(NSString *)URLString
                                                     parameters:(id)parameters
                                      constructingBodyWithBlock:(void(^)(id <AFMultipartFormData> formData))block
                                                       progress:(void(^)(NSProgress *uploadProgress))uploadProgress
                                              completionHandler:(void(^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {
    NSError *serializationError = nil;
    NSMutableURLRequest *request = nil;
    
    if (requestSerializerType == HFBaseHTTPRequestSerializerTypeHuaTi) {
        request = [self.htRequestSerializer multipartFormRequestWithMethod:@"POST" URLString:URLString parameters:parameters constructingBodyWithBlock:block error:&serializationError];
    } else if (requestSerializerType == HFBaseHTTPRequestSerializerTypeLaiJuCai) {
        request = [self.ljcRequestSerializer multipartFormRequestWithMethod:@"POST" URLString:URLString parameters:parameters constructingBodyWithBlock:block error:&serializationError];
    } else if (requestSerializerType == HFBaseHTTPRequestSerializerTypeLaiJuCai) {
        request = [self.ljcSignRequestSerializer multipartFormRequestWithMethod:@"POST" URLString:URLString parameters:parameters constructingBodyWithBlock:block error:&serializationError];
    } else {
        if (completionHandler) {
            dispatch_async(self.URLSessionManager.completionQueue ?: dispatch_get_main_queue(), ^{
                completionHandler(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:@{
                    NSLocalizedDescriptionKey: @"Invalid Request Serializer Type In HTTP Request Manager",
                }]);
            });
        }
        return nil;
    }

    if (serializationError) {
        if (completionHandler) {
            dispatch_async(self.URLSessionManager.completionQueue ?: dispatch_get_main_queue(), ^{
                completionHandler(nil, nil, serializationError);
            });
        }
        return nil;
    }

    return [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:completionHandler];
}

#pragma mark - URLSessionManager

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                               uploadProgress:(void(^)(NSProgress *uploadProgress))uploadProgress
                             downloadProgress:(void(^)(NSProgress *downloadProgress))downloadProgress
                            completionHandler:(void(^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {
    return [self.URLSessionManager dataTaskWithRequest:request
                                        uploadProgress:uploadProgress
                                      downloadProgress:downloadProgress
                                     completionHandler:completionHandler];
}

- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
                                                 progress:(void(^)(NSProgress *uploadProgress))uploadProgress
                                        completionHandler:(void(^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {
    return [self.URLSessionManager uploadTaskWithStreamedRequest:request
                                                        progress:uploadProgress
                                               completionHandler:completionHandler];
}



@end

